package org.example.myAop.service.impl;

import jakarta.annotation.Resource;
import org.example.myAop.dao.UserDao;
import org.example.myAop.entity.User;
import org.example.myAop.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author 莫磊
 * @date 2025/7/31
 * @description
 */
@Service
public class UserServiceImpl implements UserService {

	@Resource
	private UserDao userDao;

	@Resource(type = OtherServiceImpl.class)
	private UserService otherService;

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void addUser(List<User> list) {

		int i = userDao.addUser(list);
		if (i == list.size()) {
			System.out.println("添加用户成功");
		} else {
			throw new RuntimeException("添加用户失败");
		}

		// 只保存一个用户
		try {
			// 这个嵌套事务的话必须要这个方法在spring的管理中，否则不会生效。
			// addUserForOne(list.get(0))，不如调用内部的方法的话就没有生效
			otherService.addUserForOne(list.get(0));
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (userDao.queryUser().size() > 10) {
			throw new RuntimeException("用户数量超过10个，不能添加，当前用户数量：" + (userDao.queryUser().size() - list.size()));
		}
	}

	@Override
	@Transactional
	public void updateUser(List<User> list) {
		int i = userDao.updateUser(list);
		if (i == list.size()) {
			System.out.println("更新用户成功");
		} else {
			throw new RuntimeException("更新用户失败");
		}
	}

	/**
	 * 隔离级别只在读取中生效，写操作不生效
	 * @return
	 */
	@Override
	@Transactional(isolation = Isolation.READ_COMMITTED)
	public List<User> queryUser() {
		return userDao.queryUser();
	}

	@Override
	public void testAop() {
		System.out.println("测试切面功能");
	}

	/**
	 * 测试事务的传播性
	 * @param user
	 */
	@Override
	public void addUserForOne(User user) {
		user.setName(user.getName() + "addUserForOne");
		userDao.addUser(Arrays.asList(user));
		String str = null;
		str.toString();
	}
}
